<?php

/**
 * Formalize
 * 
 * Formalize should be a simple class to create dynamic
 * forms.
 * With this class, it should be very easy to construct a
 * form as wished to fit in every project.
 * 
 * @author Koos van Egmond <flamefingers at gmail dot com>
 * @version 0.1
 */
 
// Start loading necessary classes first
require_once dirname(__FILE__).'/fields/formalizefield.class.php';
require_once dirname(__FILE__).'/filters/formalizefilter.class.php';


class Formalize {
		
	/**
	 * The version of Formalize
	 * @var String
	 */
	public $version = '0.1';
	
	/**
	 * All fields will be stored in this prop
	 * @var Array
	 */
	private $fields = array();
	
	/**
	 * Some properties to hold common data for the form
	 * @var Mixed
	 */
	private	$method,
			$enctype,
			$formname,
			$attributes;
	
	/**
	 * The current html template to assign to newly added
	 * form fields.
	 * @var String
	 */		
	public $fieldtemplate;
	
	/**
	 * Set properties to hold html for prepending and appending the
	 * fields HTML with.
	 * @var String
	 */
	public $beforeFields,
		   $afterFields;
	
	/**
	 * The constructor method to start the form
	 * @param String $method The method to post the form
	 * @param String $enctype The encoding type to use for the form
	 * @param String $name Pass an optional name to the form tag
	 * @param String|Array $attributes Optional HTML attributes for the form tag
	 */
	public function __construct($method='post', $enctype=false, $name=false, $attributes=false) {
		
		// Set the attributes in the private properties
		$this->method = $method;
		$this->enctype = $enctype;
		$this->formname = $name;
		$this->attributes = $attributes;
		
		// Set default fieldtemplate to work with tables
		$fieldtemplateHtml = '<tr><td><label for="[_NAME_]">[_LABEL_]</label></td><td>[_FIELD_]</td></tr>';
		$this->fieldtemplate = $fieldtemplateHtml;
		
		// Set default html to put before and after the
		// fields to work with tables
		$this->beforeFields = '<table border="0"><tbody>';
		$this->afterFields = '</tbody></table>';
	}
	
	/**
	 * Add a field to the fields array
	 * @param String $type The type of field
	 * @param String $name The form friendly name to use (also as ID)
	 * @param String $label The label of the field
	 * @param Boolean $required Wether the current field is mendatory or not
	 * @param Array $filters The input fielters which the value has to pass
	 * @param String $default The default text to fill the with
	 * @param String|Array $attributes Optional attributes to add in the HTML
	 * @param Mixed	$extra A param to pass extra options for the type of field
	 */
	public function add($type='text', $name, $label=false, $required=false, $filters=array(), $default=false, $attributes=false, $extra=false) {
		
		// Construct a classname for the current field
		$fieldClassName = 'Field'.ucfirst($type);
		
		// Check if the class exists, lazy load it otherwise
		if (!class_exists($fieldClassName)) {
			
			// Set filename and path of the field class
			$fieldClassFile = $type.'.field.php';
			$fieldClassPath = dirname(__FILE__).'/fields/'.$fieldClassFile;
			
			// Check if the file exists
			if (!file_exists($fieldClassPath)) {
				
				// Throw a user error
				trigger_error('Field class or file does not exists for field '.$type, E_USER_ERROR);
				exit;
			}
			
			// Require the field class
			require_once $fieldClassPath;
		}
		
		// Define the field and configure it
		$field = new $fieldClassName($type, $name, $label, $default, $extra);
		
		// Set the container HTML
		$field->container = $this->fieldtemplate;
		
		// Set required?
		$field->setRequired($required);
		
		// Add filters?
		if ($filters) {
			$field->addFilters($filters);
		}
		
		// Add extra attributes?
		if ($attributes) {
			$field->addAttributes($attributes);
		}
		
		// Set the extra parameters
		$field->extra = $extra;
		
		// All done, add the field to the fields array
		$this->fields[] = $field;
	}
	
	/**
	 * Render the HTML with the given options
	 * @return String
	 */
	public function render() {
		
		// Start HTML with the form field
		$html = '<form method="%s" %s>';
		
		// Set additional attributes form the form
		$formAttribs  = ($this->enctype) ? "enctype=\"{$this->enctype}\" " : '';
		$formAttribs .= ($this->formname) ? "name=\"{$this->formname}\" " : '';
		
		// Add additional user set attributes for the form
		if (is_array($this->attributes) && !empty($this->attributes)) {
			
			foreach ($this->attributes as $attribKey => $attribVal) {
				
				$formAttribs .= "{$attribKey}=\"{$attribVal}\" ";
			}
		}
		
		// Add post method and additional attributes to the form tag
		$html = sprintf($html, $this->method, $formAttribs);
		
		// Add optional content if beforeFields is set
		if ($this->beforeFields) $html .= $this->beforeFields;
		
		// Loop through the fields, construct them and add html
		foreach ($this->fields as $fieldObject) {
			
			$html .= $fieldObject->render();
		}
		
		// Add optional content if afterFields is set
		if ($this->afterFields) $html .= $this->afterFields;
		
		// Close the html form tag
		$html .= '</form>';
		
		// Return the rendered HTML
		return $html;
	}
}
